package com.health.es.temp;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.health.trans.common.util.GenericUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.WordUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author nqlz
 */
@Slf4j
@Component
public class EsClassOperations {

    @Getter
    public static Set<Class<?>> ES_CLASSES;
    public static Set<String> packageNames;
    private static final Cache<String, Class<?>> CLASS_CACHE = CacheUtil.newLRUCache(200);

    private static final String TB_ = "tb_";
    private static final String ES = "Es";


    @PostConstruct
    public void init() {
        initEsClass(packageNames.toArray(new String[]{}));
    }

    public static Set<Class<?>> initEsClass(String... packageNames) {
        return ES_CLASSES = Stream.of(packageNames)
                .map(ClassUtil::scanPackage)
                .flatMap(Set::stream)
                .collect(Collectors.toSet());
    }

    public static <R> Class<R> getEsClass(String tableName) {
        Class<?> aClass = CLASS_CACHE.get(tableName, () -> {
            Optional<Class<?>> tableClass = ES_CLASSES.parallelStream()
                    .filter(i -> StrUtil.equalsAnyIgnoreCase(i.getSimpleName(), getTableKeys(tableName)))
                    .findFirst();
            if (tableClass.isPresent()) {
                CLASS_CACHE.put(tableName, tableClass.get());
                return tableClass.get();
            }
            return null;
        });
        return GenericUtil.get(aClass);
    }

    private static String[] getTableKeys(String tableName) {
        List<String> values = new ArrayList<>();
        if (StrUtil.startWithIgnoreCase(tableName, TB_)) {
            String replace = tableName.replace(TB_, "");
            values.add(StrUtil.toCamelCase(ES + replace));
            values.add(replace);
        } else if (!StrUtil.startWithIgnoreCase(tableName, ES)) {
            values.add(ES + tableName);
        }
        values.add(tableName);
        return ArrayUtil.toArray(values, String.class);
    }

    public static <T, J> EsCustomRepository<T, J> getRepository(Class<T> tClass) {
        String beanName = WordUtils.uncapitalize(tClass.getSimpleName() + "Repository");
        return getBean(beanName, tClass.getSimpleName());
    }

    private static <T> T getBean(String beanName, String className) {
        try {
            return SpringUtil.getBean(beanName);
        } catch (Exception e) {
            ExceptionUtil.wrapRuntimeAndThrow(className + " 的 repository 不存在。");
        }
        return null;
    }

}
